package com.file.parser.socialsecurity;

import com.file.bo.ResponseData;
import com.file.bo.socialsecurity.HenanIndividualRecordSheet;
import com.file.bo.socialsecurity.HenanInsuranceParticipation;
import com.file.constant.ErrorCode;
import com.file.parser.BasePdfParser;
import com.file.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import technology.tabula.*;
import technology.tabula.detectors.SpreadsheetDetectionAlgorithm;
import technology.tabula.extractors.SpreadsheetExtractionAlgorithm;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class HenanSocialSecurityPdfParser  extends BasePdfParser {

    public ResponseData<String> parseHenanSocialSecurityPdfToJson(String daId, String filePath) {
        log.info("parseHenanSocialSecurityPdfToJson started, daId:{}", daId);
        String json = null;

        try {
            if (filePath.contains("cbzm")) {
                HenanInsuranceParticipation henanInsuranceParticipation = parseHenanInsuranceParticipation(filePath);
                json = JsonUtils.convertObjectToJson(henanInsuranceParticipation);
            } else if (filePath.contains("qyd")) {//NOSONAR
                HenanIndividualRecordSheet hananIndividualRecordSheet = parseHenanIndividualRecordSheet(filePath);
                json = JsonUtils.convertObjectToJson(hananIndividualRecordSheet);//NOSONAR
            } else {
                log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseHenanSocialSecurityPdfToJson failed, new type not supported");
                return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
            }
        } catch (Exception e) {
            log.error("OnError|{}||{}|{}|{}|{}", ErrorCode.FILE_PARSE_EXCEPTION.getCode(), daId, "", "", "parseJiangsuSocialSecurityPdfToJson failed", e);
            return new ResponseData<>(null, ErrorCode.FILE_PARSE_EXCEPTION.getCode(), ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
        }

        log.info("parseHenanSocialSecurityPdfToJson completed, daId:{}", daId);
        return new ResponseData<>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
    }

    private HenanInsuranceParticipation parseHenanInsuranceParticipation(String filePath) {
        HenanInsuranceParticipation henanInsuranceParticipation = parseHenanInsuranceParticipationHeader(filePath);
        List<List<String>> rowList = parseFileToRowList(filePath);
        parseListToBO(rowList, henanInsuranceParticipation);
        return henanInsuranceParticipation;
    }

    private HenanInsuranceParticipation parseHenanInsuranceParticipationHeader(String filePath) {
        HenanInsuranceParticipation henanInsuranceParticipation = new HenanInsuranceParticipation();
        String pdfText = getPdfTextByStripper2(filePath)
                .replace(System.getProperty("line.separator", "\n"), StringUtils.EMPTY);
        String year = "";
        if (pdfText.contains("表单验证号码")) {
            String formVerifyNo = pdfText.substring(pdfText.indexOf("表单验证号码") + 6, pdfText.indexOf("河南省社会保险个人参保证明")).trim();
            henanInsuranceParticipation.setFormVerifyNo(formVerifyNo);
        }
        if (pdfText.contains("个人参保证明（") && pdfText.contains("）单位")) {
            year = pdfText.substring(pdfText.indexOf("个人参保证明（") + 7, pdfText.indexOf("）单位"))
                    .replaceAll(StringUtils.SPACE, "");
        } else {
            Pattern pattern = Pattern.compile("\\d{4}年");
            Matcher matcher = pattern.matcher(pdfText);
            if (matcher.find()) {
                year = matcher.group();
            }
        }
        if (year.contains("年")) {
            year = year.substring(0, 4);
        }
        String description = pdfText.substring(pdfText.lastIndexOf("说明：") + 3, pdfText.lastIndexOf("电子签章预留"));
        String printTime = pdfText.substring(pdfText.lastIndexOf("打印时间：") + 5)
                .replaceAll(StringUtils.SPACE, "");

        henanInsuranceParticipation.setYear(year);
        henanInsuranceParticipation.setDescription(description);
        henanInsuranceParticipation.setPrintTime(printTime);
        return  henanInsuranceParticipation;
    }

    private HenanIndividualRecordSheet parseHenanIndividualRecordSheet(String filePath) { //NOSONAR
        HenanIndividualRecordSheet henanIndividualRecordSheet = new HenanIndividualRecordSheet();
        return henanIndividualRecordSheet;
    }

    private void parseListToBO(List<List<String>> rowList, HenanInsuranceParticipation henanInsuranceParticipation) {
        List<HenanInsuranceParticipation.ParticipationInSocialInsurance> participationInSocialInsuranceList = new ArrayList<>();
        henanInsuranceParticipation.setParticipationInSocialInsuranceList(participationInSocialInsuranceList);
        HenanInsuranceParticipation.PaymentDetails paymentDetails = new HenanInsuranceParticipation.PaymentDetails();
        henanInsuranceParticipation.setPaymentDetails(paymentDetails);
        HenanInsuranceParticipation.BasicEndowmentInsurance basicEndowmentInsurance
                = new HenanInsuranceParticipation.BasicEndowmentInsurance();
        HenanInsuranceParticipation.UnemploymentInsurance unemploymentInsurance
                = new HenanInsuranceParticipation.UnemploymentInsurance();
        HenanInsuranceParticipation.EmploymentInjuryInsurance employmentInjuryInsurance
                = new HenanInsuranceParticipation.EmploymentInjuryInsurance();

        henanInsuranceParticipation.getPaymentDetails().setBasicEndowmentInsurance(basicEndowmentInsurance);
        List<HenanInsuranceParticipation.PaymentRecord> basicEndowmentInsurancePaymentRecordList = new ArrayList<>();
        basicEndowmentInsurance.setPaymentRecordList(basicEndowmentInsurancePaymentRecordList);

        henanInsuranceParticipation.getPaymentDetails().setUnemploymentInsurance(unemploymentInsurance);
        List<HenanInsuranceParticipation.PaymentRecord> unemploymentInsurancePaymentRecordList = new ArrayList<>();
        unemploymentInsurance.setPaymentRecordList(unemploymentInsurancePaymentRecordList);

        henanInsuranceParticipation.getPaymentDetails().setEmploymentInjuryInsurance(employmentInjuryInsurance);
        List<HenanInsuranceParticipation.PaymentRecord> employmentInjuryInsurancePaymentRecordList = new ArrayList<>();
        employmentInjuryInsurance.setPaymentRecordList(employmentInjuryInsurancePaymentRecordList);
        String year = henanInsuranceParticipation.getYear();

        String sectionName = "";

        for (int i = 0; i < rowList.size(); i++) {
            List<String> cellList = rowList.get(i);
            if (StringUtils.isBlank(cellList.get(1))) {
                continue;
            } else if (StringUtils.equals(cellList.get(1), "证件类型")) {
                sectionName = "证件类型";
            } else if (StringUtils.equals(cellList.get(1), "社会保障号码")) {
                sectionName = "社会保障号码";
            } else if (StringUtils.equals(cellList.get(1), "单位名称")) {
                sectionName = "单位名称";
                continue;
            } else if (StringUtils.equalsAny(cellList.get(1), "缴费明细情况", "月份")) {
                continue;
            } else if (StringUtils.equals(cellList.get(1), "参保时间")) {
                sectionName = "参保时间";
                continue;
            } else if (StringUtils.equals(cellList.get(1), "缴费基数")) {
                sectionName = "缴费基数";
                continue;
            } else if (StringUtils.equals(cellList.get(1), "说明:")) {
                sectionName = "说明"; //NOSONAR
                break;
            }

            switch (sectionName) {//NOSONAR
                case "证件类型":
                    henanInsuranceParticipation.setIdType(cellList.get(2));
                    henanInsuranceParticipation.setIdNo(cellList.get(4).replaceAll(StringUtils.SPACE, ""));
                    break;
                case "社会保障号码":
                    henanInsuranceParticipation.setSocialSecurityNumber(cellList.get(2).replaceAll(StringUtils.SPACE, ""));
                    henanInsuranceParticipation.setName(cellList.get(4));
                    henanInsuranceParticipation.setGender(cellList.get(6));
                    break;
                case "单位名称":
                    HenanInsuranceParticipation.ParticipationInSocialInsurance participationInSocialInsurance
                            = new HenanInsuranceParticipation.ParticipationInSocialInsurance();
                    participationInSocialInsurance.setUnitName(cellList.get(1));
                    participationInSocialInsurance.setInsuranceType(cellList.get(2));
                    participationInSocialInsurance.setStartDate(cellList.get(3).replaceAll(StringUtils.SPACE, ""));
                    participationInSocialInsurance.setEndDate(cellList.get(4).replaceAll(StringUtils.SPACE, ""));
                    participationInSocialInsuranceList.add(participationInSocialInsurance);
                    break;
                case "参保时间":
                    basicEndowmentInsurance.setInsurancePeriod(cellList.get(1).replaceAll(StringUtils.SPACE, ""));
                    basicEndowmentInsurance.setPaymentStatus(cellList.get(2));
                    unemploymentInsurance.setInsurancePeriod(cellList.get(3).replaceAll(StringUtils.SPACE, ""));
                    unemploymentInsurance.setPaymentStatus(cellList.get(4));
                    employmentInjuryInsurance.setInsurancePeriod(cellList.get(5).replaceAll(StringUtils.SPACE, ""));
                    employmentInjuryInsurance.setPaymentStatus(cellList.get(6));
                    break;
                case "缴费基数":
                    HenanInsuranceParticipation.PaymentRecord basicEndowmentInsurancePaymentRecord
                            = new HenanInsuranceParticipation.PaymentRecord();
                    basicEndowmentInsurancePaymentRecord.setYearMonth(year.concat(cellList.get(1)));
                    basicEndowmentInsurancePaymentRecord.setPaymentBase(cellList.get(2).replaceAll(StringUtils.SPACE, ""));
                    basicEndowmentInsurancePaymentRecord.setPaymentStatus(convertSymbolToText(cellList.get(3)));
                    basicEndowmentInsurancePaymentRecordList.add(basicEndowmentInsurancePaymentRecord);

                    HenanInsuranceParticipation.PaymentRecord unemploymentInsurancePaymentRecord
                            = new HenanInsuranceParticipation.PaymentRecord();
                    unemploymentInsurancePaymentRecord.setYearMonth(year.concat(cellList.get(1)));
                    unemploymentInsurancePaymentRecord.setPaymentBase(cellList.get(4).replaceAll(StringUtils.SPACE, ""));
                    unemploymentInsurancePaymentRecord.setPaymentStatus(convertSymbolToText(cellList.get(5)));
                    unemploymentInsurancePaymentRecordList.add(unemploymentInsurancePaymentRecord);

                    HenanInsuranceParticipation.PaymentRecord employmentInjuryInsurancePaymentRecord
                            = new HenanInsuranceParticipation.PaymentRecord();
                    employmentInjuryInsurancePaymentRecord.setYearMonth(year.concat(cellList.get(1)));
                    employmentInjuryInsurancePaymentRecord.setPaymentBase(cellList.get(6).replaceAll(StringUtils.SPACE, ""));
                    employmentInjuryInsurancePaymentRecord.setPaymentStatus(convertSymbolToText(cellList.get(7)));
                    employmentInjuryInsurancePaymentRecordList.add(employmentInjuryInsurancePaymentRecord);
                    break;
            }

        }
    }

    private List<List<String>> parseFileToRowList(String filePath) {
        // 1. 读取文件
        File pdf = new File(filePath);

        //页面所有table的记录，每一个元素代表下面一条记录cellList
        List<List<String>> rowList = new ArrayList<>();

        // 2. pdfbox读取PDDocument
        try (PDDocument pdfDocument = PDDocument.load(pdf)) {
            // 3. tabula新建ObjectExtractor和NurminenDetectionAlgorithm，同时准备接收表格Rectangle的结构
            ObjectExtractor objectExtractor = new ObjectExtractor(pdfDocument);
            SpreadsheetDetectionAlgorithm detectionAlgorithm = new SpreadsheetDetectionAlgorithm();
            Map<Integer, List<Rectangle>> pageNumber2RectangleListMap = new HashMap<>();//key为页的序号， value为对应的Rectangle的list

            // 4. 获取每页的PageIterator
            PageIterator pageIterator = objectExtractor.extract();

            // 5. 解析每页的Rectangle
            // 如果单页pdf中有多个Rectangle，则解析出来的List<Rectangle>会有多个对象
            while (pageIterator.hasNext()) {
                Page page = pageIterator.next();
                List<Rectangle> rectangleList = detectionAlgorithm.detect(page);
                if (rectangleList.size() > 0) {
                    pageNumber2RectangleListMap.put(page.getPageNumber(), rectangleList);
                }
            }

            // 6.通过table位置获取表格具体内容
            SpreadsheetExtractionAlgorithm extractionAlgorithm = new SpreadsheetExtractionAlgorithm();

            // 如果单页pdf中有多个表格，则解析出来的List<Rectangle>会有多个对象
            for (Map.Entry<Integer, List<Rectangle>> entry : pageNumber2RectangleListMap.entrySet()) {
                Page page = objectExtractor.extract(entry.getKey());
                Rectangle rectangle = null;

                List<Rectangle> rectangleList = entry.getValue();
                for (Rectangle r : rectangleList) {
                    double rectangleHeight = r.getHeight();
                    if (Double.compare(rectangleHeight, 0) > 0) {
                        rectangle = r;
                        break;
                    }
                }
                if (rectangle == null) {
                    throw new RuntimeException("rectangle is null.");
                }

                if (entry.getKey() > 1) {
                    rectangle.setTop(rectangle.getTop());
                }
                rectangle.setBottom(rectangle.getBottom());
                Page area = page.getArea(rectangle);

                // 如果每页有多个表格，解析每一个table
                List<Table> tableList = extractionAlgorithm.extract(area);
                for (Table table : tableList) {
                    for (int i = 0; i < table.getRowCount(); i++) {
                        List<String> cellList = new ArrayList<>();//一条记录，每个单元格占一个元素
                        for (int j = 0; j < table.getColCount(); j++) {
                            cellList.add(table.getCell(i, j).getText(false));
                        }
                        rowList.add(cellList);
                    }
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }

        return rowList;
    }

    private String  convertSymbolToText(String symbol) {
        String text = symbol;
        if (StringUtils.equals(symbol, "●")) {
            text = "已经实缴";
        } else if (StringUtils.equals(symbol, "△")) {
            text = "欠费";
        } else if (StringUtils.equals(symbol, "○")) {
            text = "外地转入";
        } else if (StringUtils.equals(symbol, "-")) {
            text = "未制定计划";
        }

        return text;
    }

    public static void main(String[] args) {
        String filePath = "D:\\data\\file\\socialsecurity\\河南\\app-gjzwfw-dzsb_cbzm.pdf";
        HenanSocialSecurityPdfParser henanSocialSecurityPdfParser = new HenanSocialSecurityPdfParser();
        String json = henanSocialSecurityPdfParser.parseHenanSocialSecurityPdfToJson("", filePath).getData();
        System.out.println(json);
    }

}
